package JAVA300.第十一章多线程;

/**
 * DCL单例模式 double checked lock
 * ：懒汉式套路上加入并发控制，多线程环境下 对外存在一个对象
 * 1.构造器私有化--》避免外部new构造器
 * 2.提供私有的静态属性--》存储对象地址
 * 3.提供公共静态方法--》获取属性
 */

public class thread_19_others_5DoubleedChecked {

    //2.提供私有的静态属性-私有实例--不被调用：懒汉式
    //volatile参考底下的7 咩有它可能访问一个咩有初始化的对象
    private static volatile thread_19_others_5DoubleedChecked instance;

    //1。私有化构造器
    private thread_19_others_5DoubleedChecked(){

    }

    //3.提供公共静态方法--》获取属性
    public static thread_19_others_5DoubleedChecked getInstance(){

        //6 如果a在里面建了对象 后面来的线程如果因为锁而一直等待 效率降低
        //加入double checking避免不必要的同步
        if (null != instance){
            return instance;//
        }


        //4在这里创建对象
        //5如果不加控制，创建对象操作耗时时，第二个线程会在第一个正在建对象的同时加入进来创建另一个对象了
        //加入synchronized 原来是丢入this对象 这里就丢入模子class
        synchronized (thread_19_others_5DoubleedChecked.class){
            if (null == instance){//正常的创建对象操作
                instance = new thread_19_others_5DoubleedChecked();
                //7 代码重排
                //这步骤的过程：开辟空间--初始化对象信息--返回对象的地址给引用
                //第二步很慢，第三步很有可能先于第二步返回
                //也就是a还咩有创建完，b线程就进来获得返回对象，结果为空
                //在实例声明中加入volatile
            }
        }


        return instance;
    }
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            System.out.println(thread_19_others_5DoubleedChecked.getInstance());
        });
        thread.start();

        System.out.println(thread_19_others_5DoubleedChecked.getInstance());//同一个地址说明仅有一个底箱
    }
}
